// use common_uu::string::StringExentd;
use std::fmt::Debug;

/// 错误枚举
#[allow(non_camel_case_types)]
#[derive(Debug)]
pub enum Error
where
    Self: Sized,
{
    /// String: 导航的 URL
    Navigation {
        url: String,
        error: String,
    },

    // 导航异常2(dyn std::fmt::Debug),
    /// String: 哪个按钮
    TabNotFind(String),

    /// (哪个元素, 错误信息)
    ElementNotFound(String, String),

    /// (哪个元素, 错误信息)
    /// 拖动元素
    Drag(String, String),

    /// (哪个元素, 错误信息)
    ClickInvalid(String, String),

    /// (哪个元素, 错误信息)
    InputError(String, String),

    /// (哪个元素, 错误信息)
    InputReturnValue(String, String),

    /// (哪个元素, 错误信息)
    GetValue(String, String),

    /// 数值转换出错
    NumConv(String),

    /// IO异常
    IOError(String),

    /// 异常描述
    Error(String),

    /// 异常描述
    Error2(String, String),

    /// 操作中出现的明确错误提示,比如: 缴款时银行卡里的金额不足
    /// 注意: 返回此错误将直接返回,不进行重试
    ErrorAlert(String),

    /// RPA错误
    /// 注意: 返回此错误将直接返回,不进行重试
    RpaError(String),

    Other(String),
}

impl Into<String> for Error {
    fn into(self) -> String {
        self.to_string()
    }
}

impl std::error::Error for Error {}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", format!("{:?}", self))
    }
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Self {
        Self::IOError(format!("{:?}", err))
    }
}

impl From<Box<dyn std::error::Error + Send + Sync>> for Error {
    fn from(err: Box<dyn std::error::Error + Send + Sync>) -> Self {
        Self::IOError(format!("{}", err.to_string()))
    }
}

impl From<Box<dyn std::error::Error>> for Error {
    fn from(err: Box<dyn std::error::Error>) -> Self {
        Self::Error(format!("{:?}", err))
    }
}

impl From<&str> for Error {
    fn from(err: &str) -> Self {
        Self::Error(err.to_string())
    }
}

impl From<String> for Error {
    fn from(err: String) -> Self {
        Self::Error(err)
    }
}

// impl From<common::MyError> for EtaxError {
//     fn from(err: common::MyError) -> Self {
//         Self::Error(err.to_string())
//     }
// }

// impl From<Box<common::MyError>> for EtaxError {
//     fn from(err: Box<common::MyError>) -> Self {
//         Self::Error(err.to_string())
//     }
// }

impl From<std::num::ParseFloatError> for Error {
    fn from(err: std::num::ParseFloatError) -> Self {
        Self::NumConv(format!("{:?}", err))
    }
}

impl From<std::num::ParseIntError> for Error {
    fn from(err: std::num::ParseIntError) -> Self {
        Self::NumConv(format!("{:?}", err))
    }
}

impl<T> From<std::sync::mpsc::SendError<T>> for Error {
    fn from(_err: std::sync::mpsc::SendError<T>) -> Self {
        Self::Error(format!("管道操作SendError出错: {:?}", _err))
    }
}

impl From<thirtyfour::error::WebDriverError> for Error {
    fn from(err: thirtyfour::error::WebDriverError) -> Self {
        use thirtyfour::error::WebDriverError as E;
        match err {
            E::NotFound(s1, s2) => Self::ElementNotFound(s1, s2),
            E::NoSuchElement(e) => Self::ElementNotFound(e.error.clone(), e.to_string()),
            E::NoSuchFrame(e) => Self::ElementNotFound(e.error.clone(), e.to_string()),
            E::NoSuchAlert(e) => Self::ElementNotFound(e.error.clone(), e.to_string()),
            E::NoSuchWindow(e) => Self::ElementNotFound(e.error.clone(), e.to_string()),
            E::Timeout(e) => Self::ElementNotFound("Timeout".to_string(), e.to_string()),
            _ => Self::Other(format!("{:?}", err)),
        }
    }
}

impl<E: Debug> From<retry::Error<E>> for Error {
    fn from(err: retry::Error<E>) -> Self {
        Self::Error(format!("重试出错: {:?}", err))
    }
}

impl From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Self {
        Self::Error(format!("Json序列化出错: {:?}", err))
    }
}
